#ifndef E_ITEM_META_FUNCTION_H
#define E_ITEM_META_FUNCTION_H

#include <cstdint>
#include <stdarg.h>
#include "EString.h"
#include <functional>
#include <DefineLibCommon.h>
#include <DefineCommon.h>
#include <EItemMetaProperty.h>
#include <EVariant.h>
/*This delegate code is not used in final version, but the delegate.h file is still in this project*/
// #include <delegate/delegate.h>

/**This class is used to represent a class's functions,
 * which is same with QMetaMethod. This can:
 * 1.get the parameter list.
 * 2.get return type 
 * 3.called by outside
 * */
struct EItemMetaFunctionData;
class EItemMetaFunction;
typedef SmartPtr(EItemMetaFunction) EItemMetaFunctionPtr;
class COMMON_DLL EItemMetaFunction
{
public:
    enum FunType
    {
        FREE,
        CONSTRUCTOR,
        CLASS_MEMBER
    };

    /**This class is used to represent a class's functions,*/
    EItemMetaFunction();
    virtual ~EItemMetaFunction();

    void addProperty(EItemMetaPropertyPtr p);
    EItemMetaPropertyPtr getProperty(int index);
    size_t getPropertyCount();

    void setOwner(intptr_t owner);
    intptr_t getOwner();

    void setFunType(FunType type);
    FunType getFunType();

    void setName(const EString& name);
    EString getName();

    void setGroupName(const EString& name);
    EString getGroupName();

    void setReturnProperty(EItemMetaPropertyPtr p);
    EItemMetaPropertyPtr getReturnProperty();

    void call( EVariant* result, EList<EVariant*> vList);
    void call( EVariant* result);
    void call( EVariant* result, EVariant* v1);
    void call( EVariant* result, EVariant* v1, EVariant* v2);
    void call( EVariant* result, EVariant* v1, EVariant* v2, EVariant* v3);
    void call( EVariant* result, EVariant* v1, EVariant* v2, EVariant* v3, EVariant* v4);
    void call( EVariant* result, EVariant* v1, EVariant* v2, EVariant* v3, EVariant* v4, EVariant* v5);

    // std::function<EVariant()> m_fun_0;
    // std::function<EVariant(EVariant)> m_fun_1;
    // std::function<EVariant(EVariant,EVariant)> m_fun_2;
    // std::function<EVariant(EVariant,EVariant,EVariant)> m_fun_3;
    // std::function<EVariant(EVariant,EVariant,EVariant)> m_fun_4;
    // std::function<EVariant(EVariant,EVariant,EVariant,EVariant,EVariant)> m_fun_5;


    /**if FunType==CLASS_MEMBER, this m_owner is the object pointer*/
    FunType m_funType;
    EString m_name;
    EString m_groupName;

protected:
    /**Subclass must rewrite this function
     * owner usually be nullptr even for class member function*/
    virtual void callInternal( intptr_t owner, ... );

    EItemMetaFunctionData* m_data;

};

#endif // E_ITEM_META_FUNCTION_H
